#!/usr/bin/env python3
"""
cross_platform_fingerprint.py
无需管理员权限, Windows & Linux 通用
生成 32 位十六进制硬件指纹
"""

import hashlib
import platform
import uuid
import subprocess
import sys

def _read_file(path):
    try:
        with open(path, "r", encoding="ascii") as f:
            return f.read().strip()
    except Exception:
        return ""

def _wmic(query):
    """运行 wmic 并返回首行非空结果"""
    try:
        out = subprocess.check_output(
            query, shell=True, stderr=subprocess.DEVNULL
        ).decode("utf-8", errors="ignore")
        for line in out.splitlines():
            line = line.strip()
            if line and line != query.split()[-1]:  # 跳过标题行
                return line
    except Exception:
        pass
    return ""

def get_cpu_short():
    """返回 CPU 品牌+主频(非特权可读)"""
    system = platform.system()
    if system == "Windows":
        brand = _wmic("wmic cpu get name /value").split("=", 1)[-1].strip()
        clock = _wmic("wmic cpu get maxclockspeed /value").split("=", 1)[-1].strip()
        return f"{brand}@{clock}MHz"
    else:  # Linux
        info = _read_file("/proc/cpuinfo")
        for line in info.splitlines():
            if line.startswith("model name"):
                return line.split(":", 1)[1].strip()
        return "UnknownCPU"

def get_board_uuid():
    """主板 UUID(普通用户可读)"""
    system = platform.system()
    if system == "Windows":
        return _wmic("wmic csproduct get uuid /value").split("=", 1)[-1].strip()
    else:  # Linux
        return _read_file("/sys/class/dmi/id/product_uuid")

def get_mac():
    """取第一块真实网卡 MAC"""
    node = uuid.getnode()
    if (node >> 40) & 0xFF == 0xFF:  # 如果返回的是随机值
        return "000000000000"
    return uuid.UUID(int=node).hex[-12:]

def genfingerprint() -> str:
    cpu = get_cpu_short()
    uuid_board = get_board_uuid()
    mac = get_mac()
    raw = "|".join([cpu, uuid_board, mac]).encode("utf-8")
    return hashlib.sha256(raw).hexdigest()[:32]  # 32 字符

# --------- 演示 ---------
if __name__ == "__main__":
    print("Hardware fingerprint:", genfingerprint())
